package com.yunlong.service.impl;

import com.github.pagehelper.PageHelper;
import com.yunlong.common.TokenInfo;
import com.yunlong.common.exception.SysException;
import com.yunlong.dto.*;
import com.yunlong.entity.Geeker;
import com.yunlong.entity.Manager;
import com.yunlong.entity.User;
import com.yunlong.exception.UserException;
import com.yunlong.form.*;
import com.yunlong.mapper.ManagerMapper;
import com.yunlong.mapper.UserMapper;
import com.yunlong.redis.RedisRepository;
import com.yunlong.service.ManagerService;
import com.yunlong.util.ListCastObject;
import com.yunlong.util.Md5Util;
import com.yunlong.util.StringUtil;
import com.yunlong.util.TokenUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.BOBYQAOptimizer;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * @author guorui
 * @date 2021-07-18 10:07
 */
@Slf4j
@Service
public class ManagerServiceImpl implements ManagerService {
    private final int pageSize = 5;
    @Resource
    private ManagerMapper managerMapper;
    @Resource
    private UserMapper userMapper;
    @Resource
    private RedisRepository redisRepository;
    /**
     * 给管理员展示待审批的注册用户
//     * @param page 前端传的查询页数
     * @return List<AllRegistersDto>
     */
    @Override
    public List allUsers() {
        //自动分页查询，设置在查询语句前面就OK，只对后面的第一条语句起作用
        //page是前端返回的页数，pageSize=5.每页有5条语句
//        PageHelper.startPage(page,pageSize);

        log.info("users");
        List<getUserDto> allUsers = managerMapper.selectAllUsers();
        List Users = new ArrayList();
        List<getUserDto> CpuUsers = new ArrayList<getUserDto>();
        List<getUserDto> OsUsers = new ArrayList<getUserDto>();
        List<getUserDto> AiUsers = new ArrayList<getUserDto>();
        for(int i=0;i<allUsers.size();i++){
            switch (allUsers.get(i).getUserDirection()){
                case "CPU":
                    CpuUsers.add(allUsers.get(i));
                    break;
                case "操作系统":
                    OsUsers.add(allUsers.get(i));
                    break;
                case "人工智能":
                    AiUsers.add(allUsers.get(i));
                    break;
            }
        }
        Users.add(CpuUsers);
        Users.add(OsUsers);
        Users.add(AiUsers);
        return Users;
    }

    /**
     * 给超级管理员展示所有管理员
     *Integer page
//     * @param page 前端传的查询页数
     * @return List<AllRegistersDto>
     */
    @Override
    public List allManagers() {
        //自动分页查询，设置在查询语句前面就OK，只对后面的第一条语句起作用
        //page是前端返回的页数，pageSize=5.每页有5条语句
//        PageHelper.startPage(page,pageSize);
        log.info("ssssssssss");
        List<AllGeekersDto> allmanagers = managerMapper.selectAllManagers();
        List Mangaers = new ArrayList();
        List<AllGeekersDto> leaders = new ArrayList<AllGeekersDto>();
        List<AllGeekersDto> geekers = new ArrayList<AllGeekersDto>();
        List<AllGeekersDto> makers = new ArrayList<AllGeekersDto>();
        for(int i=0;i<allmanagers.size();i++){
            switch (allmanagers.get(i).getGeekerStation()){
                case "院务委员":
                    leaders.add(allmanagers.get(i));
                    break;
                case "极客":
                    geekers.add(allmanagers.get(i));
                    break;
                case "创客":
                    makers.add(allmanagers.get(i));
                    break;
            }
        }
        Mangaers.add(leaders);
        Mangaers.add(geekers);
        Mangaers.add(makers);
        return Mangaers;
    }

    /**
     * 管理员新增用户（后台管理系统）
     *
     * @param userRegisterForm
     */
    @Override
    public String userRegister(UserRegisterForm userRegisterForm) {
        if(null != userMapper.selectByUserId(userRegisterForm.getUserId())){
            log.info("该学号已存在，请重新输入");
            throw new UserException("该学号已存在，请重新输入");
        }else if(null != userMapper.selectByEmail(userRegisterForm.getUserEmail())){
            log.info("邮箱已存在，请重新输入");
            throw new UserException("邮箱已存在，请重新输入");
        }else{
            log.info("验证通过");
            String userPassword = userRegisterForm.getUserPassword();
            if(userRegisterForm.getUserPassword().equals("")){
                userPassword = "123456abc";
            }
            //md5加密后的密码
            String userPassword2 = Md5Util.MD5Encode(userPassword);
            userRegisterForm.setUserPassword(userPassword2);
            managerMapper.userRegister(userRegisterForm);
            managerMapper.userInfoRegister(userRegisterForm);
            return "新增用户成功";
        }
    }
    /**
     * 管理员批量导入用户信息文件
     */
    @Override
    public MessageSuccessDto uploadUsersFile(InputStream inputStream){
        try {
            Workbook wb = null;
            wb = WorkbookFactory.create(inputStream);
            inputStream.close();
            // Excel的页签数量，有几页，就是有几个子表
            int sheet_size = wb.getNumberOfSheets();
            System.out.println("此excel共有"+sheet_size+"页");
            for (int index = 0; index < sheet_size; index++) {
                List<List> outerList=new ArrayList<List>();
                // 每个页签创建一个Sheet对象
                Sheet sheet = wb.getSheetAt(index);
                // sheet.getRows()返回该页的总行数
                int lastRowNum  = sheet.getLastRowNum();
                //开始遍历行
                //外层循环每走一次，遍历完一页的所有内容
                for (int i = 0; i < lastRowNum; i++) {
                    List innerList=new ArrayList();
                    // sheet.getColumns()返回该页的总列数
                    Row row = sheet.getRow(i);
                    if (row==null){
                        innerList = null;
                        outerList.add(i,innerList);
                        continue;
                    }
                    int firstColumn = row.getFirstCellNum();
                    int lastColumn = row.getLastCellNum();
                    //开始遍历列
                    for (int j = firstColumn; j < lastColumn; j++) {
                        //获取row行的第j列的内容
                        Cell cellInfo = row.getCell(j);
                        if (cellInfo==null){
                            innerList.add("null");
                        }else{
                            innerList.add(cellInfo.toString());
                        }
                    }
                    //至此遍历完此行的所有列
                    outerList.add(i,innerList);
                }
                usersRegister(outerList);
                List<UserRegisterForm> userRegisterForms = ListCastObject.getUsers(outerList);
                managerMapper.usersRegister(userRegisterForms);
                managerMapper.usersInfoRegister(userRegisterForms);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InvalidFormatException e) {
            e.printStackTrace();
        }
        MessageSuccessDto registerSuccessDto = new MessageSuccessDto();
        registerSuccessDto.setMessage("批量新增用户成功");
        return registerSuccessDto;
    }
    /**
     * 管理员批量新增用户
     */
    public void usersRegister(List excelList){
        //行数
        int rows = excelList.size();
        for (int i = 0; i < rows; i++) {
            List list = (List) excelList.get(i);
            //遍历列
            for (int j = 0; j < list.size(); j++) {
                System.out.print(list.get(j)+"\t");
            }
            System.out.println();
        }

    }
    public static File multipartToFile(MultipartFile multipart) throws IllegalStateException, IOException
    {
        File convFile = new File( multipart.getOriginalFilename());
        multipart.transferTo(convFile);
        return convFile;
    }
    /**
     * 判断Excel的版本,获取Workbook
     * @param file
     * @return
     * @throws IOException
     */
    public static Workbook getWorkbook(MultipartFile file) throws IOException {
        Workbook wb = null;
        FileInputStream in = new FileInputStream(multipartToFile(file));
        if(file.getName().endsWith("xls")){
            //HSSFWorkbook : 这个类有读取和.xls 格式和写入Microsoft Excel文件的方法。它与微软Office97-2003版本兼容。
            wb = new HSSFWorkbook(in);
        }else if(file.getName().endsWith("xlsx")){
            //XSSFWorkbook : 这个类有读写Microsoft Excel和OpenOffice的XML文件的格式.xls或.xlsx的方法。它与MS-Office版本2007或更高版本兼容。
            wb = new XSSFWorkbook(in);
        }
        return wb;
    }

    /**
     * 超级管理员新增普通管理员
     * @param managerRegisterForm
     * @return String 新增成功
     */
    @Override
    public String managerRegister(ManagerRegisterForm managerRegisterForm) {
        User geeker = userMapper.selectByUserId(managerRegisterForm.getGeekerId());
        if(null == geeker){
            throw new UserException("该学号不存在，请检查");
        }else{
            String managerName =geeker.getUserName();
            String projectInfo = managerRegisterForm.getProjectInfo();
            String managerStation = managerRegisterForm.getGeekerStation();
            String managerPhone = geeker.getUserPhone();
            String managerDirection = geeker.getUserDirection();
            managerMapper.managerRegister(geeker.getUserId(),managerName,managerDirection,projectInfo,managerStation,managerPhone);
            return "新增管理员成功";
        }
    }

    /**
     * 超级管理员删除管理员
     * @param managerIdForm
     * @return MessageSuccessDto
     */
    @Override
    public String managerDeleted(ManagerIdForm managerIdForm) {
        List<String> managerID = managerIdForm.getManagerId();
        for(String managerId : managerID){
            if(managerId.equals("")||managerId==null){
                log.info("该管理员不存在，请检查");
                throw new UserException(managerId+"管理员不存在，请检查");
            }
            String oldToken = redisRepository.selectManagerToken(managerId);
            if (null != oldToken) {
                //删除原有的token
                redisRepository.deleteManagerToken(oldToken);
                redisRepository.deleteLoginManagerToken(managerId);
            }
        }
        managerMapper.deletedManagers(managerID);
        managerMapper.deletedUsers(managerID);
        return "管理员已删除";
    }

    /**
     * 管理员删除用户
     * @param deletedUsers
     */
    @Override
    public String deletedUsers(UserApprovalForm deletedUsers) {
        List<String> userID = deletedUsers.getUserId();
        for(String userId : userID){
            if(userId.equals("")||userId==null){
                log.info("该用户不存在，请检查");
                throw new UserException(userId+"用户不存在，请检查");
            }
            String oldToken = redisRepository.selectUserToken(userId);
            if (null != oldToken) {
                //删除原有的token
                redisRepository.deleteAccessToken(oldToken);
                redisRepository.deleteLoginAccessToken(userId);
            }
        }
        //多表联合删除
        managerMapper.deletedUsers(userID);
        return "用户已删除";
    }

    /**
     * 管理员登录
     * @param managerLoginForm
     * @return LoginSuccessDto
     */
    @Override
    public LoginSuccessDto managerLogin(ManagerLoginForm managerLoginForm) {
        //密码经过md5加密处理 -32位小写
//        log.info(managerLoginForm.getGeekerEmail()+managerLoginForm.getGeekerPassword());
        String result = Md5Util.MD5Encode(managerLoginForm.getGeekerPassword());
        User manager = userMapper.selectByEmail(managerLoginForm.getGeekerEmail());
        if (null == manager) {
            throw new UserException("邮箱不存在！");
        } else if (!manager.getUserPassword().equals(result)) {
            log.info(result);
            log.info(manager.getUserPassword());
            throw new SysException("密码错误");
        } else {
            Geeker geeker = managerMapper.selectManagerById(manager.getUserId());
            String oldToken = redisRepository.selectManagerToken(geeker.getGeekerId());
            if (null != oldToken) {
                //其实是在另一个页面登录，又执行了一次登录操作，所以要删除旧的token信息，更新token
                log.info("异地登录！");
                //如果存在异地登录，删除原有的token   "MANAGER:accessToken"
                redisRepository.deleteManagerToken(oldToken);
//                "MANAGER_TOKEN:managerId"
                redisRepository.deleteLoginManagerToken(geeker.getGeekerId());
            }
            //得到一个accessToken，生成tokenInfo
            TokenInfo tokenInfo = new TokenInfo();
            tokenInfo.setAccessToken(TokenUtil.genToken());
            tokenInfo.setUserId(geeker.getGeekerId());
            LoginSuccessDto messageSuccessLoginDto = ManagerServiceImpl.getMessageSuccessLoginDtoByManager(geeker, tokenInfo);
            //保存这个超级管理员和token信息
            redisRepository.saveManagerAccessToken(tokenInfo);
            redisRepository.saveManagerLoginAccessToken(tokenInfo);
            return messageSuccessLoginDto;
        }
    }
    /**
     * 得到超级管理员登录成功返回的一个token信息
     * @param manager
     * @return
     */
    public static LoginSuccessDto getMessageSuccessLoginDtoByManager(Geeker manager, TokenInfo tokenInfo){
        LoginSuccessDto messageSuccessLoginDto = new LoginSuccessDto();
        //这里看前端具体需要什么再更改吧
        messageSuccessLoginDto.setUserName(manager.getGeekerName());
        messageSuccessLoginDto.setUserId(manager.getGeekerId());
        messageSuccessLoginDto.setUserPhone(manager.getGeekerPhone());
        messageSuccessLoginDto.setAccessToken(tokenInfo.getAccessToken());
        return messageSuccessLoginDto;
    }
    /**
     * 管理员激活用户账号
     *
     * @param userApprovalForm
     */
    @Override
    public String approvalRegister(UserApprovalForm userApprovalForm) {
        List<String> userID = userApprovalForm.getUserId();
        for(String userId : userID){
            if(userId.equals("")||userId==null){
                log.info("该用户不存在，请检查");
                throw new UserException(userId+"用户不存在，请检查");
            }
        }
        managerMapper.approvalRegister(userID);
        return "管理员已激活用户账号";
    }

    /**
     * 管理员冻结用户账号
     *
     * @param userRejectForm
     */
    @Override
    public String rejectRegister(UserApprovalForm userRejectForm) {
        List<String> userID = userRejectForm.getUserId();
        for(String userId : userID){
            if(userId.equals("")||userId==null){
                log.info("该用户不存在，请检查");
                throw new UserException(userId+"用户不存在，请检查");
            }
        }
        managerMapper.rejectRegister(userID);
        return "管理员已冻结用户账号";
    }

    /**
     * 管理员退出登录
     *
     * @param managerId
     */
    @Override
    public String logOut(String managerId) {
        Geeker manager = managerMapper.selectManagerById(managerId);
        if (null == manager) {
            log.info("此学号不存在！");
            throw new UserException("管理员id不存在！");
        }
        String oldToken = redisRepository.selectManagerToken(manager.getGeekerId());
        if (null != oldToken) {
            //删除原有的token
            redisRepository.deleteManagerToken(oldToken);
            redisRepository.deleteLoginManagerToken(manager.getGeekerId());
            return "用户退出登录成功";
        }else {
            return "用户退出登录失败";
        }
    }

    /**
     * 管理员按学号或姓名查询学员
     */
    @Override
    public List<getUserDto> selectUser(String userInfo) {
        boolean flag = StringUtil.isNumeric(userInfo);
        getUserDto userDto = new getUserDto();
        if(flag==true){
            userDto = managerMapper.selectUserById(userInfo);
        }else{
            userDto = managerMapper.selectUserByName(userInfo);
//            System.out.println(userDto.getUserResume());
        }
        List<getUserDto> userList = new ArrayList<getUserDto>();
        userList.add(userDto);

        return userList;
    }
}
